#include "connection_handler.h"
#include "command.h"
#include "logger.h"
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sstream>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <fstream>
#include "md5.h"
#include <cstring>

// 文件元数据结构
struct FileMetadata
{
    bool is_upload;
    uint64_t file_size;
    char filename[256];
};

struct ChunkHeader
{
    uint64_t offset;
    uint64_t size;
};

// 获取文件元数据
bool get_file_metadata(const std::string &path, FileMetadata &metadata)
{
    struct stat st;
    if (stat(path.c_str(), &st))
    {
        return false;
    }

    metadata.is_upload = false;
    metadata.file_size = st.st_size;
    strncpy(metadata.filename, path.c_str(), sizeof(metadata.filename) - 1);
    metadata.filename[sizeof(metadata.filename) - 1] = '\0';
    return true;
}

// 接收上传的文件数据
void receive_file_data(int client_fd, const std::string &file_path)
{
    // 确保目录存在
    size_t pos = file_path.find_last_of('/');
    if (pos != std::string::npos)
    {
        std::string dir_path = file_path.substr(0, pos);
        if (access(dir_path.c_str(), F_OK)) {
            // 目录不存在，尝试创建
            std::string cmd = "mkdir -p " + dir_path;
            if (system(cmd.c_str()))
            {
                throw std::runtime_error("Cannot create directory: " + dir_path);
            }
        }
    }
    const size_t BUFFER_SIZE = 1024 * 1024; // 1MB
    char buffer[BUFFER_SIZE];

    int fd = open(file_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1)
    {
        throw std::runtime_error("Cannot open file for writing: " + file_path);
    }

    try
    {
        ChunkHeader header;
        while (true)
        {
            // 接收块头
            ssize_t bytes_received = recv(client_fd, &header, sizeof(header), MSG_WAITALL);
            if (bytes_received <= 0)
            {
                break;
            }

            // 接收块数据
            uint64_t remaining = header.size;
            while (remaining > 0)
            {
                size_t to_read = std::min(static_cast<uint64_t>(BUFFER_SIZE), remaining);
                bytes_received = recv(client_fd, buffer, to_read, 0);
                if (bytes_received <= 0)
                {
                    throw std::runtime_error("Connection closed during file transfer");
                }

                if (write(fd, buffer, bytes_received) != bytes_received)
                {
                    throw std::runtime_error("Error writing to file");
                }

                remaining -= bytes_received;
            }
        }
    }
    catch (...)
    {
        close(fd);
        throw;
    }

    close(fd);
}

// 发送下载的文件数据
void send_file_data(int client_fd, const std::string &file_path)
{
    const size_t BUFFER_SIZE = 1024 * 1024; // 1MB
    char buffer[BUFFER_SIZE];

    int fd = open(file_path.c_str(), O_RDONLY);
    if (fd == -1)
    {
        throw std::runtime_error("Cannot open file for reading: " + file_path);
    }

    try
    {
        struct stat st;
        fstat(fd, &st);
        off_t offset = 0;
        off_t file_size = st.st_size;

        while (offset < file_size)
        {
            size_t to_send = std::min(static_cast<off_t>(BUFFER_SIZE), file_size - offset);

            // 发送块头
            ChunkHeader header{offset, to_send};
            send(client_fd, &header, sizeof(header), 0);

            // 发送块数据
            ssize_t bytes_read = read(fd, buffer, to_send);
            if (bytes_read <= 0)
            {
                throw std::runtime_error("Error reading from file");
            }

            ssize_t bytes_sent = send(client_fd, buffer, bytes_read, 0);
            if (bytes_sent != bytes_read)
            {
                throw std::runtime_error("Error sending file data");
            }

            offset += bytes_sent;
        }
    }
    catch (...)
    {
        close(fd);
        throw;
    }

    close(fd);
}

// 发送响应给客户端
void send_response(int client_fd, const std::string &response)
{
    std::string formatted = response;
    if (formatted.size() < 3 ||
        !isdigit(formatted[0]) ||
        !isdigit(formatted[1]) ||
        !isdigit(formatted[2]) ||
        formatted[3] != ' ')
    {
        formatted = "200 " + response;
    }

    if (formatted.size() < 2 || formatted.substr(formatted.size() - 2) != "\r\n")
    {
        formatted += "\r\n";
    }

    const char *data = formatted.c_str();
    size_t total = formatted.size();
    ssize_t sent = 0;

    while (sent < total)
    {
        ssize_t n = send(client_fd, data + sent, total - sent, 0);
        if (n <= 0)
        {
            throw std::runtime_error("Failed to send response");
        }
        sent += n;
    }
}

void handle_connection(int client_fd)
{
    Logger::info("Handling connection: " + std::to_string(client_fd));

    try
    {
        // 创建连接上下文（包含独立的命令处理器）
        ConnectionContext context(client_fd);
        char buffer[1024];
        time_t last_activity = time(nullptr);

        while (true)
        {
            // 检查空闲超时（300秒）
            if (time(nullptr) - last_activity > 300)
            {
                Logger::info("Connection idle timeout: " + std::to_string(client_fd));
                send_response(client_fd, "421 Service not available, closing control connection");
                break;
            }

            // 接收命令
            ssize_t bytes_received = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
            last_activity = time(nullptr); // 更新最后活动时间

            if (bytes_received > 0)
            {
                buffer[bytes_received] = '\0';

                // 移除可能的回车换行
                std::string command(buffer);
                if (!command.empty() && command[command.size() - 1] == '\n')
                {
                    command.pop_back();
                    if (!command.empty() && command[command.size() - 1] == '\r')
                    {
                        command.pop_back();
                    }
                }

                Logger::info("Received command: " + command);

                // 处理特殊命令
                if (command == "QUIT")
                {
                    send_response(client_fd, "221 Goodbye");
                    break;
                }

                // 处理文件传输命令
                if (command.find("UPLOAD") == 0 || command.find("DOWNLOAD") == 0)
                {
                    // 解析文件传输命令
                    std::istringstream iss(command);
                    std::string cmd, local_path, remote_path;
                    iss >> cmd >> local_path >> remote_path;

                    if (local_path.empty() || remote_path.empty())
                    {
                        send_response(client_fd, "501 Invalid syntax for file transfer command");
                        continue;
                    }

                    // 获取绝对路径
                    std::string abs_remote_path = context.cmd_handler->get_absolute_path(remote_path);

                    // 发送开始传输响应
                    send_response(client_fd, "150 Starting file transfer");

                    // 执行文件传输
                    try
                    {
                        if (cmd == "UPLOAD")
                        {
                            receive_file_data(client_fd, abs_remote_path);

                            // 计算并验证MD5
                            std::string md5 = MD5Calculator::calculate(abs_remote_path);
                            char client_md5[33] = {0};
                            recv(client_fd, client_md5, 32, 0);

                            if (md5 == client_md5)
                            {
                                send_response(client_fd, "226 File transfer successful, MD5 verified");
                            }
                            else
                            {
                                send_response(client_fd, "426 File transfer failed, MD5 mismatch");
                            }
                        }
                        else if (cmd == "DOWNLOAD")
                        {
                            // 发送文件数据
                            send_file_data(client_fd, abs_remote_path);

                            // 接收MD5验证结果
                            char result;
                            recv(client_fd, &result, 1, 0);
                            if (result == 1)
                            {
                                send_response(client_fd, "226 File transfer successful");
                            }
                            else
                            {
                                send_response(client_fd, "426 File transfer failed, MD5 mismatch");
                            }
                        }
                    }
                    catch (const std::exception &e)
                    {
                        Logger::error("File transfer error: " + std::string(e.what()));
                        send_response(client_fd, "451 File transfer error: " + std::string(e.what()));
                    }
                    continue;
                }

                // 处理普通命令
                try
                {
                    std::string response = context.cmd_handler->process(command);
                    send_response(client_fd, response);
                }
                catch (const std::exception &e)
                {
                    Logger::error("Command processing error: " + std::string(e.what()));
                    send_response(client_fd, "500 Internal server error: " + std::string(e.what()));
                }
            }
            else if (bytes_received == 0)
            {
                // 客户端关闭连接
                Logger::info("Connection closed by client: " + std::to_string(client_fd));
                break;
            }
            else
            {
                // 处理错误
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    // 非阻塞模式下没有数据可读，继续等待
                    continue;
                }
                else
                {
                    Logger::error("recv error: " + std::string(strerror(errno)));
                    break;
                }
            }
        }
    }
    catch (const std::exception &e)
    {
        Logger::error("Connection handling error: " + std::string(e.what()));
        send_response(client_fd, "500 Internal server error");
    }

    close(client_fd);
    Logger::info("Connection closed: " + std::to_string(client_fd));
}
std::string handle_upload(const std::vector<std::string> &args)
{
    if (args.size() < 2)
    {
        return "501 Missing arguments for UPLOAD command";
    }
    return "150 Ready to receive file";
}

std::string handle_download(const std::vector<std::string> &args)
{
    if (args.size() < 2)
    {
        return "501 Missing arguments for DOWNLOAD command";
    }

    struct stat st;
    if (stat(args[0].c_str(), &st))
    {
        return "550 File not found: " + args[0];
    }

    std::ostringstream oss;
    oss << "150 Opening BINARY mode data connection for " << args[0]
        << " (" << st.st_size << " bytes)";
    return oss.str();
}